#region Imported Namespaces


using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

using AvalonDock;


#endregion


namespace WtfManager.UIManager
{
  ///<summary>
  /// Gets an information about control.
  ///</summary>
  public class UIControlInfo
  {
    #region Fields


    private readonly UIAssemblyInfo _assemblyInfo;
    private readonly List<Attribute> _attributes;
    private readonly Type _controlType;


    #endregion


    #region Constructors/Finalizers


    ///<summary>
    /// Default UIControlInfo constructor.
    ///</summary>
    ///<param name="assemblyInfo">A source <see cref="UIAssemblyInfo"/>.</param>
    ///<param name="controlType">The type of control.</param>
    public UIControlInfo(UIAssemblyInfo assemblyInfo, Type controlType)
    {
      _assemblyInfo = assemblyInfo;
      _controlType = controlType;
      _attributes = new List<Attribute>();

      object[] attributes = _controlType.GetCustomAttributes(true);

      if (attributes == null)
      {
        return;
      }

      foreach (object attribute in attributes)
      {
        if (attribute is Attribute)
        {
          _attributes.Add((Attribute)attribute);
        }
      }
    }


    #endregion


    #region Properties/Indexers


    ///<summary>
    /// Gets a source <see cref="UIAssemblyInfo">assembly</see>.
    ///</summary>
    public UIAssemblyInfo AssemblyInfo
    {
      get
      {
        return _assemblyInfo;
      }
    }


    /// <summary>
    /// Gets the control type.
    /// </summary>
    public Type ControlType
    {
      get
      {
        return _controlType;
      }
    }


    ///<summary>
    /// Returns true, if a control type is a content container.
    ///</summary>
    public bool IsContentContainer
    {
      get
      {
        return IsOfType<ContentControl>() && HasAttribute<ContentContainerAttribute>();
      }
    }


    /// <summary>
    /// Gets a value indicating whether this <see cref="UIControlInfo"/> is panel control.
    /// </summary>
    /// <value>
    /// 	<c>true</c> if this <see cref="UIControlInfo"/> is panel control; otherwise, <c>false</c>.
    /// </value>
    public bool IsPanelControl
    {
      get
      {
        return IsOfType<DockableContent>() && HasAttribute<PanelControlAttribute>();
      }
    }

    ///<summary>
    /// Returns true, if a control type is a startup window.
    ///</summary>
    public bool IsStartupWindow
    {
      get
      {
        return IsSubclassOf<Window>() && HasAttribute<StartupWindowAttribute>();
      }
    }


    #endregion


    #region Methods


    ///<summary>
    /// Checks whether a specified data Type is a valid content Type of control.
    ///</summary>
    ///<param name="type">A Type to check.</param>
    ///<returns>Returns true if a specified data Type is a valid content Type of control, otherwise false.</returns>
    public bool IsValidContentType(Type type)
    {
      if (IsContentContainer)
      {
        foreach (Attribute attribute in _attributes)
        {
          if (!(attribute is ContentContainerAttribute))
          {
            continue;
          }

          var containerAttribute = (ContentContainerAttribute)attribute;

          if (containerAttribute.StrictMatch)
          {
            if (containerAttribute.ContentType.FullName == type.FullName)
            {
              return true;
            }
          }
          else if (containerAttribute.ContentType.IsAssignableFrom(type))
          {
            return true;
          }
        }
      }

      return false;
    }


    /// <summary>
    /// Returns true if a control is subclass of specified Type.
    /// </summary>
    /// <typeparam name="T">The type to check this control type against.</typeparam>
    public bool IsSubclassOf<T>()
    {
      return IsSubclassOf(typeof(T));
    }


    /// <summary>
    /// Returns true if a control is subclass of specified Type.
    /// </summary>
    public bool IsSubclassOf(Type type)
    {
      return _controlType.IsSubclassOf(type);
    }


    /// <summary>
    /// Returns true if a control is of specified Type or is a subclass of specified Type.
    /// </summary>
    /// <typeparam name="T">The type to check this control type against.</typeparam>
    public bool IsOfType<T>()
    {
      return _controlType == typeof(T) || _controlType.IsSubclassOf(typeof(T));
    }


    /// <summary>
    /// Returns true if a control is of specified Type or is a subclass of specified Type.
    /// </summary>
    public bool IsOfType(Type type)
    {
      return _controlType == type || IsSubclassOf(type);
    }


    private bool HasAttribute<T>() where T: Attribute
    {
      foreach (Attribute attribute in _attributes)
      {
        if (attribute is T)
        {
          return true;
        }
      }

      return false;
    }


    public T GetAttribute<T>() where T: Attribute
    {
      foreach (Attribute attribute in _attributes)
      {
        if (attribute is T)
        {
          return (T)attribute;
        }
      }

      return null;
    }


    ///<summary>
    /// Creates an instance of control.
    ///</summary>
    ///<returns>An instance of control.</returns>
    public object CreateInstance()
    {
      return _assemblyInfo.CreateInstance(_controlType);
    }


    #endregion
  }
}